package com.onlineauction.entities;

import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.onlineauction.helpers.Constants;
import com.onlineauction.helpers.Constants.Category;

public class Item extends GenericEntity {

	private String owner = null;
	private Category category = null;
	private String productName = null;
	private Long itemID = null;

	public Item(String owner, Category category, String productName, boolean toCreate) {
		this.owner = owner;
		this.category = category;
		this.productName = productName;
		if (toCreate) {
			this.createAndStroeItemEntity();
		}
	}

	public Item(Long itemID) {
		Entity entity = getEntity(Constants.ITEM, itemID);
		if (entity != null) {
			this.itemID = entity.getKey().getId();
			this.owner = (String) entity.getProperty(Constants.OWNER);
			this.category = Category.valueOf((String) entity.getProperty(Constants.CATEGORY));
			this.productName = (String) entity.getProperty(Constants.PRODUCT_NAME);
		}
	}

	private void createAndStroeItemEntity() {
		Entity entity = new Entity(Constants.ITEM);
		entity.setProperty(Constants.CATEGORY, category.toString());
		entity.setProperty(Constants.OWNER, owner);
		entity.setProperty(Constants.PRODUCT_NAME, productName);
		String lowerCaseName = productName;
		if (productName != null) {
			lowerCaseName = productName.toLowerCase();
		}
		entity.setProperty((Constants.PRODUCT_NAME_ALIAS), lowerCaseName);

		Key key = storeEntity(entity);
		if (key != null) {
			this.itemID = key.getId();
		}
	}

	public static List<Item> getItemsOfOwner(String owner) {
		if (owner == null || owner.length() == 0) {
			return new ArrayList<Item>();
		}
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Query q = new Query(Constants.ITEM).addFilter(Constants.OWNER, FilterOperator.EQUAL, owner);

		Iterable<Entity> entities = ds.prepare(q).asIterable();
		List<Item> items = new ArrayList<Item>();
		for (Entity entity : entities) {
			Item item = new Item((String) entity.getProperty(Constants.OWNER),
					Category.valueOf((String) entity.getProperty(Constants.CATEGORY)),
					(String) entity.getProperty(Constants.PRODUCT_NAME), false);
			item.itemID = entity.getKey().getId();
			items.add(item);
		}

		return items;
	}

	public static List<Item> searchForAllItems() {
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Query q = new Query(Constants.ITEM);

		Iterable<Entity> entities = ds.prepare(q).asIterable();
		List<Item> items = new ArrayList<Item>();
		for (Entity entity : entities) {
			Item item = new Item((String) entity.getProperty(Constants.OWNER),
					Category.valueOf((String) entity.getProperty(Constants.CATEGORY)),
					(String) entity.getProperty(Constants.PRODUCT_NAME), false);
			item.itemID = entity.getKey().getId();
			items.add(item);
		}

		return items;
	}

	public static List<Item> searchItemsByCategory(Category category) {
		String categoryName = category.toString();

		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Query q = new Query(Constants.ITEM).addFilter(Constants.CATEGORY, FilterOperator.EQUAL,
				categoryName);

		Iterable<Entity> entities = ds.prepare(q).asIterable();
		List<Item> items = new ArrayList<Item>();
		for (Entity entity : entities) {
			Item item = new Item((String) entity.getProperty(Constants.OWNER),
					Category.valueOf((String) entity.getProperty(Constants.CATEGORY)),
					(String) entity.getProperty(Constants.PRODUCT_NAME), false);
			item.itemID = entity.getKey().getId();
			items.add(item);
		}

		return items;
	}

	public static List<Item> searchItemsByProductName(String productName) {
		String lowerCaseName = productName;
		if (productName != null) {
			lowerCaseName = productName.toLowerCase();
		}
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Query q = new Query(Constants.ITEM).addFilter(Constants.PRODUCT_NAME_ALIAS,
				FilterOperator.EQUAL, lowerCaseName);

		Iterable<Entity> entities = ds.prepare(q).asIterable();
		List<Item> items = new ArrayList<Item>();
		for (Entity entity : entities) {
			Item item = new Item((String) entity.getProperty(Constants.OWNER),
					Category.valueOf((String) entity.getProperty(Constants.CATEGORY)),
					(String) entity.getProperty(Constants.PRODUCT_NAME), false);
			item.itemID = entity.getKey().getId();
			items.add(item);
		}

		return items;
	}

	public static List<Item> searchItemsByProductNameInCategory(String productName,
			Category category) {
		
		String categoryName = category.toString();
		
		String lowerCaseName = productName;
		if (productName != null) {
			lowerCaseName = productName.toLowerCase();
		}
		
		Filter nameFilter = new FilterPredicate(Constants.PRODUCT_NAME_ALIAS, FilterOperator.EQUAL, lowerCaseName);
		Filter categoryFilter = new FilterPredicate(Constants.CATEGORY, FilterOperator.EQUAL, categoryName);
		Filter compositeFilter = CompositeFilterOperator.and(nameFilter, categoryFilter);
		
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Query q = new Query(Constants.ITEM).setFilter(compositeFilter);

		Iterable<Entity> entities = ds.prepare(q).asIterable();
		List<Item> items = new ArrayList<Item>();
		for (Entity entity : entities) {
			Item item = new Item((String) entity.getProperty(Constants.OWNER),
					Category.valueOf((String) entity.getProperty(Constants.CATEGORY)),
					(String) entity.getProperty(Constants.PRODUCT_NAME), false);
			item.itemID = entity.getKey().getId();
			items.add(item);
		}

		return items;
	}

	public Long getItemID() {
		return itemID;
	}

	public String getOwner() {
		return owner;
	}

	public Category getCategory() {
		return category;
	}

	public String getProductName() {
		return productName;
	}

}
